<?php
/**
 * 百度编辑器上传图片
 */
defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );
/**
 * UMEditor编辑器通用上传类
 */
class Uploader {
	private $fileField; // 文件域名
	private $file; // 文件上传对象
	private $config; // 配置信息
	private $oriName; // 原始文件名
	private $fileName; // 新文件名
	private $fullName; // 完整文件名,即从当前配置目录开始的URL
	private $fileSize; // 文件大小
	private $fileType; // 文件类型
	private $stateInfo; // 上传状态信息,
	private $stateMap = array ( // 上传状态映射表，国际化用户需考虑此处数据的国际化
			"SUCCESS", // 上传成功标记，在UEditor中内不可改变，否则flash判断会出错
			"文件大小超出 upload_max_filesize 限制",
			"文件大小超出 MAX_FILE_SIZE 限制",
			"文件未被完整上传",
			"没有文件被上传",
			"上传文件为空",
			"POST" => "文件大小超出 post_max_size 限制",
			"SIZE" => "文件大小超出网站限制",
			"TYPE" => "不允许的文件类型",
			"DIR" => "目录创建失败",
			"IO" => "输入输出错误",
			"UNKNOWN" => "未知错误",
			"MOVE" => "文件保存时出错",
			"DIR_ERROR" => "创建目录失败" 
	);
	
	/**
	 * 构造函数
	 *
	 * @param string $fileField
	 *        	表单名称
	 * @param array $config
	 *        	配置项
	 * @param bool $base64
	 *        	是否解析base64编码，可省略。若开启，则$fileField代表的是base64编码的字符串表单名
	 */
	public function __construct($fileField, $config, $base64 = false) {
		$this->fileField = $fileField;
		$this->config = $config;
		$this->stateInfo = $this->stateMap [0];
		$this->upFile ( $base64 );
	}
	
	/**
	 * 上传文件的主处理方法
	 *
	 * @param
	 *        	$base64
	 * @return mixed
	 */
	private function upFile($base64) {
		// 处理base64上传
		if ("base64" == $base64) {
			$content = $_POST [$this->fileField];
			$this->base64ToImage ( $content );
			return;
		}
		
		// 处理普通上传
		$file = $this->file = $_FILES [$this->fileField];
		if (! $file) {
			$this->stateInfo = $this->getStateInfo ( 'POST' );
			return;
		}
		if ($this->file ['error']) {
			$this->stateInfo = $this->getStateInfo ( $file ['error'] );
			return;
		}
		if (! is_uploaded_file ( $file ['tmp_name'] )) {
			$this->stateInfo = $this->getStateInfo ( "UNKNOWN" );
			return;
		}
		
		$this->oriName = $file ['name'];
		$this->fileSize = $file ['size'];
		$this->fileType = $this->getFileExt ();
		
		if (! $this->checkSize ()) {
			$this->stateInfo = $this->getStateInfo ( "SIZE" );
			return;
		}
		if (! $this->checkType ()) {
			$this->stateInfo = $this->getStateInfo ( "TYPE" );
			return;
		}
		
		$folder = $this->getFolder ();
		
		if ($folder === false) {
			$this->stateInfo = $this->getStateInfo ( "DIR_ERROR" );
			return;
		}
		
		$this->fullName = $folder . '/' . $this->getName ();
		
		if ($this->stateInfo == $this->stateMap [0]) {
			if (! move_uploaded_file ( $file ["tmp_name"], $this->fullName )) {
				$this->stateInfo = $this->getStateInfo ( "MOVE" );
			}
		}
	}
	
	/**
	 * 处理base64编码的图片上传
	 *
	 * @param
	 *        	$base64Data
	 * @return mixed
	 */
	private function base64ToImage($base64Data) {
		$img = base64_decode ( $base64Data );
		$this->fileName = time () . rand ( 1, 10000 ) . ".png";
		$this->fullName = $this->getFolder () . '/' . $this->fileName;
		if (! file_put_contents ( $this->fullName, $img )) {
			$this->stateInfo = $this->getStateInfo ( "IO" );
			return;
		}
		$this->oriName = "";
		$this->fileSize = strlen ( $img );
		$this->fileType = ".png";
	}
	
	/**
	 * 获取当前上传成功文件的各项信息
	 *
	 * @return array
	 */
	public function getFileInfo() {
		return array (
				"originalName" => $this->oriName,
				"name" => $this->fileName,
				"url" => $this->fullName,
				"size" => $this->fileSize,
				"type" => $this->fileType,
				"state" => $this->stateInfo 
		);
	}
	
	/**
	 * 上传错误检查
	 *
	 * @param
	 *        	$errCode
	 * @return string
	 */
	private function getStateInfo($errCode) {
		return ! $this->stateMap [$errCode] ? $this->stateMap ["UNKNOWN"] : $this->stateMap [$errCode];
	}
	
	/**
	 * 重命名文件
	 *
	 * @return string
	 */
	private function getName() {
		return $this->fileName = time () . rand ( 1, 10000 ) . $this->getFileExt ();
	}
	
	/**
	 * 文件类型检测
	 *
	 * @return bool
	 */
	private function checkType() {
		return in_array ( $this->getFileExt (), $this->config ["allowFiles"] );
	}
	
	/**
	 * 文件大小检测
	 *
	 * @return bool
	 */
	private function checkSize() {
		return $this->fileSize <= ($this->config ["maxSize"] * 1024);
	}
	
	/**
	 * 获取文件扩展名
	 *
	 * @return string
	 */
	private function getFileExt() {
		return strtolower ( strrchr ( $this->file ["name"], '.' ) );
	}
	
	/**
	 * 按照日期自动创建存储文件夹
	 *
	 * @return string
	 */
	private function getFolder() {
		$pathStr = $this->config ["savePath"];
		if (strrchr ( $pathStr, "/" ) != "/") {
			$pathStr .= "/";
		}
		$pathStr .= date ( "Ymd" );
		if (! file_exists ( $pathStr )) {
			if (! mkdir ( $pathStr, 0777, true )) {
				return false;
			}
		}
		return $pathStr;
	}
}